﻿using UnityEngine;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Reflection.Emit;
using UnityEngine.UI;
using System;
using UnityEngine.Events;
using System.Timers;
using System.Collections.Generic;

namespace TcpSocket
{
    public class TcpSocketClient
    {
        public TcpSocketClient(string ip, int port)
        {
            IP = ip;
            Port = port;
        }

        public TcpSocketClient() { }

        string _ip = "127.0.0.1";
        public string IP { get { return _ip; } set { _ip = value; } }
        int _port = 10010;
        public int Port { get { return _port; } set { _port = value; } }

        List<string> TempSendList = new List<string>();
        //Socket client;

        /// <summary>
        /// 链接对象
        /// </summary>
        Socket clientSocket;
        /// <summary>
        /// 链接间隔时间
        /// </summary>
        float connectInterval = 1;
        /// <summary>
        /// 当前链接时间
        /// </summary>
        float connectTime = 0;
        /// <summary>
        /// 链接次数
        /// </summary>
        int connectCount = 0;
        /// <summary>
        /// 是否在连接中
        /// </summary>
        bool isConnecting = false;
        int _connCount = 7;

        string hertStr = "Server Information";

        public UnityAction<string> OnReceive = null;
        public UnityAction OnConnected = null;
        public UnityAction OnError = null;
        public UnityAction OnDisconnected = null;
        public UnityAction<int> OnConnInterval = null;

        public void Initialized()
        {
            connectCount = 0;
        }

        public void Connected(int _cCount = 7)
        {
            _connCount = _cCount;
            _connect();
        }

        //发消息
        public void Send(string message)
        {
            try
            {
                byte[] data = Encoding.UTF8.GetBytes(message);
                clientSocket.Send(data);
            }
            catch (Exception e)
            {
                TempSendList.Add(message);
                Debug.Log("报了个错: " + e);
            }
        }

        /// <summary>
        /// 断开连接，释放资源
        /// </summary>
        public void Close()
        {
            if (clientSocket != null)
            {
                clientSocket.Close();
            }
            OnDisconnected.Invoke();
        }

        /// <summary>
        /// 心跳检查 断开重连 在Update中调用才有效
        /// </summary>
        public void ConnectedInterval()
        {
            if (clientSocket != null && clientSocket.Connected == false)
            {
                //链接没有成功 计时
                connectTime += Time.deltaTime;
                if (connectTime > connectInterval && isConnecting == false)//如果时间大于链接重置时间间隔且没有链接
                {
                    if (connectCount >= _connCount)
                    {
                        clientSocket = null;
                    }
                    else
                    {
                        //链接次数增加
                        connectCount++;
                        // Debug.Log("这是第" + connectCount + "次链接");
                        _connect();//重连一次
                    }
                    OnConnInterval.Invoke(connectCount);
                }
            }
        }

        /// <summary>
        /// 链接到服务器
        /// </summary>
        void _connect()
        {
            isConnecting = true;
            //如果客户端不为空
            if (clientSocket != null)
            {
                try
                {
                    //断开连接，释放资源
                    clientSocket.Disconnect(false);
                    clientSocket.Close();
                }
                catch (Exception e)
                {
                    //Debug.Log(e.ToString());
                }
            }

            //创建新的链接(固定格式)
            clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //设置端口号和ip地址
            EndPoint endPoint = new IPEndPoint(IPAddress.Parse(IP), Port);
            //发起链接
            clientSocket.BeginConnect(endPoint, OnConnectCallBack, "");
        }
        /// <summary>
        /// 开始链接的回调
        /// </summary>
        /// <param name="ar"></param>
        void OnConnectCallBack(IAsyncResult ar)
        {
            if (clientSocket.Connected)
            {
                //链接成功
                OnConnected.Invoke();
                connectCount = 0;

                Thread th = new Thread(Receive);
                th.Start();

                foreach (var msg in TempSendList)
                {
                    Send(msg);
                }
                TempSendList.Clear();

                //获取客户端的IP和端口号  
                //IPAddress clientIP = (clientSocket.RemoteEndPoint as IPEndPoint).Address;
                //Send(clientIP + "==>" + str);
            }
            else
            {
                //链接失败 计时重置
                OnError.Invoke();
                connectTime = 0;
            }
            isConnecting = false;
            //结束链接
            clientSocket.EndConnect(ar);
        }

        //接收消息
        void Receive()
        {
            
            byte[] data = new byte[1024];//数据容器
            while (true)
            {
                if (clientSocket.Connected == false)
                    break;
                try
                {
                    int length = clientSocket.Receive(data);
                    if (length > 0)
                    {
                        string message = Encoding.UTF8.GetString(data, 0, length);
                        //Debug.Log("接收到服务器消息: => "+message);
                        //Message = message;
                        if (message != hertStr)
                        {
                            OnReceive.Invoke(message);
                        }
                    }
                }
                catch (Exception e)
                {

                }
            }
        }
    }
}
